package org.fuys.coder.domain.audit.service.policy.audit.impl;

import com.alibaba.fastjson2.JSON;
import com.aliyun.green20220302.Client;
import com.aliyun.green20220302.models.ImageModerationRequest;
import com.aliyun.green20220302.models.ImageModerationResponse;
import com.aliyun.green20220302.models.ImageModerationResponseBody;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import org.fuys.coder.common.config.AliYunOssConfig;
import org.fuys.coder.domain.config.service.impl.CoderAuditConfig;
import org.fuys.coder.domain.audit.model.event.AsyncAuditEvent;
import org.fuys.coder.domain.audit.model.event.AsyncTaskIdHolder;
import org.fuys.coder.domain.audit.model.req.AuditTask;
import org.fuys.coder.domain.audit.model.res.AuditResult;
import org.fuys.coder.domain.audit.model.vo.AuditResultLabels;
import org.fuys.coder.domain.audit.model.vo.AuditResultTypeVO;
import org.fuys.coder.domain.audit.service.policy.audit.AuditStrategy;
import org.fuys.coder.domain.audit.service.publisher.AsyncAuditEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.*;

/**
 * @projectName: fuys-low-coder
 * @package: org.fuys.coder.domain.audit.service.policy.audit
 * @className: ImageAuditStrategy
 * @author: WangJing
 * @description: 图片审核策略 这里从AuditTask中拿出来的应该是一个字符串url
 * @date: 2024/6/22 17:02
 * @version: 1.0
 */
@Service("imageAuditStrategy")
public class ImageAuditStrategy implements AuditStrategy {

    @Resource
    private CoderAuditConfig config;

    @Resource
    private AliYunOssConfig ossConfig;

    @Resource
    private AsyncAuditEventPublisher publisher;

    private Client client;

    private ExecutorService threadPoolExecutor;


    @PostConstruct
    public void initAuditStrategy(){
        try {
            Config clientConfig=new Config();
            clientConfig.setAccessKeyId(ossConfig.getAccessKeyId());
            clientConfig.setAccessKeySecret(ossConfig.getAccessKeySecret());
            clientConfig.setEndpoint("green-cip.cn-beijing.aliyuncs.com");
            this.client=new Client(clientConfig);
            threadPoolExecutor= Executors.newFixedThreadPool(config.getImageAuditCores());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public AuditResult execute(AuditTask task) {
        final String[] keys = task.getTasks();
        //为了保持统一 设置keys的第一个参数为真正的fileKey
        String taskId=null;
        if(keys.length>1){
            taskId=keys[1];
        }else{
            taskId=UUID.randomUUID().toString();
            AsyncTaskIdHolder.setTaskInfo(taskId,task);
        }
        AuditResult auditResult=new AuditResult();
        auditResult.setType(AuditResultTypeVO.ONGOING.getIndex());
        auditResult.setFinish(false);
        auditResult.setTaskId(taskId);
        doAudit(keys[0], auditResult);
        return auditResult;
    }

    private void doAudit(String key,AuditResult auditResult){
            //阿里sdk的操作步骤
            Callable<AuditResult> callable=()->{
                try {
                    RuntimeOptions runtimeOptions=new RuntimeOptions();
                    Map<String,String> serviceParas=new HashMap<>();
                    serviceParas.put("dataId", UUID.randomUUID().toString());
                    serviceParas.put("ossRegionId", ossConfig.getRegion());
                    serviceParas.put("ossBucketName",ossConfig.getBucketName());
                    serviceParas.put("ossObjectName",key);

                    ImageModerationRequest request=new ImageModerationRequest();
                    request.setService(config.getImageService());
                    request.setServiceParameters(JSON.toJSONString(serviceParas));

                    final ImageModerationResponse imageModerationResponse = client.imageModerationWithOptions(request, runtimeOptions);
                    if(!ObjectUtils.isEmpty(imageModerationResponse)){
                        if(imageModerationResponse.getStatusCode()==200){
                            final ImageModerationResponseBody body = imageModerationResponse.getBody();
                            if(body.getCode()==200){
                                final ImageModerationResponseBody.ImageModerationResponseBodyData data = body.getData();
                                final List<ImageModerationResponseBody.ImageModerationResponseBodyDataResult> result = data.getResult();
                                for (ImageModerationResponseBody.ImageModerationResponseBodyDataResult imageModerationResponseBodyDataResult : result) {
                                    final String label = imageModerationResponseBodyDataResult.getLabel();
                                    if("nonLabel".equals(label)){
                                        //如果没有标签被设置 说明还是一切正常
                                        continue;
                                    }
                                    //否则 如果存在标签被匹配了 那么说明存在嫌疑点
                                    final String like = AuditResultLabels.like(label);
                                    if(!"".equals(like)){
                                        //todo 这里并没有详细的统计 有可能未来会详细的统计
                                        if(imageModerationResponseBodyDataResult.getConfidence()>config.getImageConfidence()){
                                            auditResult.setType(AuditResultTypeVO.BLOCK.getIndex());
                                            auditResult.setMsg(like);
                                            auditResult.setFinish(true);
                                            return auditResult;
                                        }
                                    }
                                }
                            }
                            auditResult.setType(AuditResultTypeVO.PASS.getIndex());
                            auditResult.setMsg(AuditResultLabels.NORMAL.getDesc());
                            auditResult.setFinish(true);
                            return auditResult;
                        }
                    }
                    return null;
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            };
        final CompletableFuture<AuditResult> auditResultCompletableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                return callable.call();
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }, threadPoolExecutor);
        //设置事件发布 这里将发布异步审核完成
        auditResultCompletableFuture.thenApply(asyncAuditResult -> {
            AsyncAuditEvent event=new AsyncAuditEvent(this);
            event.setAuditResult(asyncAuditResult);
            publisher.publishAuditEvent(event);
            return asyncAuditResult;
        });
    }

}
